package com.sand.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sand.Exception.SandException;
import com.sand.dto.Owner.*;
import com.sand.dto.Select.UserSelect;
import com.sand.dto.merchant.merchantDto;
import com.sand.entity.buy.detail;
import com.sand.entity.buy.execution;
import com.sand.entity.buy.scheme;
import com.sand.entity.user.User;
import com.sand.feign.MerchantFeign;
import com.sand.feign.ShoppingFeign;
import com.sand.feign.UserFeign;
import com.sand.mapper.SchemeMapper;
import com.sand.result.AppHttpCodeEnum;
import com.sand.result.ResponseResult;
import com.sand.service.DetailService;
import com.sand.service.ExecutionService;
import com.sand.service.SchemeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;

@Service
public class SchemeServiceImpl extends ServiceImpl<SchemeMapper, scheme> implements SchemeService {

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private MerchantFeign merchantFeign;

    @Autowired
    private DetailService detailService;

    @Autowired
    private ShoppingFeign shoppingFeign;

    @Autowired
    private ExecutionService executionService;

    /**
     * 客户添加方案
     */
    @Override
    public String addOrUpdate(SchemeAdd schemeAdd) {
        //参数的校验和初始化
        scheme scheme = pan(schemeAdd);

        //判断设计方
        panMerchant(scheme.getMerchantid());

        //默认不添加到合同表
        scheme.setRightt(0);

        //添加
        save(scheme);

        //添加到方案预执行表
        execution execution = new execution();

        execution.setMeet(scheme.getOverr());
        execution.setMerchantid(scheme.getMerchantid());
        execution.setOwnerid(scheme.getOwnerid());
        execution.setSchemeid(scheme.getId());

        executionService.add(execution);


        return "添加方案成功";
    }


    /**
     * 客户,商家查看所有方案
     *
     * @param merchantOrOwner
     * @return
     */
    @Override
    public List<scheme> getByid(MerchantOrOwner merchantOrOwner) {

        Integer merchantid = merchantOrOwner.getMerchantid();

        Integer ownerid = merchantOrOwner.getOwnerid();

        LambdaQueryWrapper<scheme> wrapper = new LambdaQueryWrapper<>();

        //都不传
        if (merchantid == null && ownerid == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未传入要查询的用户id");
        }

        //都传入
        if (merchantid != null && ownerid != null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "不能同时查询多个数据");
        }

        //传入商家
        if (merchantid != null) {
            wrapper.eq(scheme::getMerchantid, merchantid);
            return list(wrapper);
        }

        //传入客户
        wrapper.eq(scheme::getOwnerid, ownerid);

        List<scheme> list = list(wrapper);

        return list.stream().peek(scheme -> scheme.setMaterialsmoney(null)).toList();
    }




    /**
     * 客户,商家修改方案
     *
     * @param schemeUpdate
     * @return
     */
    @Override
    public String upd(schemeUpdate schemeUpdate) {

        //获取设计师
        Integer merchantid = schemeUpdate.getMerchantid();

        //获取客户
        Integer ownerid = schemeUpdate.getOwnerid();

        //获取方案
        Integer schemeid = schemeUpdate.getSchemeid();

        //获取客户推迟时间
        String time = schemeUpdate.getTime();

        //判断是否传入方案
        if (schemeid == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未传入要修改的方案");
        }

        //操作人判断
        if (merchantid == null && ownerid == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未传入操作人");
        }

        if (merchantid != null && ownerid != null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"不能同时操作两个id");
        }

        //查询表达式
        LambdaQueryWrapper<scheme> wrapper = new LambdaQueryWrapper<>();

        //表示商家操作
        if (merchantid != null) {

            //添加设计费用
            if (schemeUpdate.getDesignmoney() == null) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "没有传入设计费用");
            }

            //判断该用户操作的是自己设计的方案
            wrapper.eq(scheme::getMerchantid, merchantid).eq(scheme::getId, schemeid);

            //查询这个方案
            scheme scheme = getOne(wrapper);

            if (scheme == null) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "当前操作人未参与该方案");
            }

            if (scheme.getRightt() != 0) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "该方案已经确认无法修改");
            }

            scheme.setDesignmoney(schemeUpdate.getDesignmoney()); //添加设计费用

            //修改
            updateById(scheme);

            return "商家添加为设计方案添加设计费用成功";
        }

        //客户操作

        //只有一个操作,客户主动推迟时间,如果传入了推迟时间,同时需要修改方案预执行的时间
        if (time == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未传入要推迟的时间");
        }

        //判断该用户操作的是自己的方案
        wrapper.eq(scheme::getOwnerid, ownerid).eq(scheme::getId, schemeid);

        //查询方案
        scheme scheme = getOne(wrapper);

        if (scheme == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "当前操作人未参与该方案");
        }

        if (scheme.getRightt() != 0) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "该方案已经确认无法修改");
        }

        //修改方案的预计审计时间
        scheme.setOverr(time);

        //修改方案
        updateById(scheme);

        //修改方案预执行
        execution execution = new execution();

        execution.setOwnerid(ownerid);
        execution.setMerchantid(merchantid);
        execution.setSchemeid(scheme.getId());
        execution.setMeet(time);

        //修改
        executionService.upd(execution);


        return "客户推迟时间成功";
    }

    /**
     * 客户删除方案
     *
     * @param id
     */
    @Override
    public Integer down(Integer id) {

        scheme scheme = getById(id);

        if (scheme == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"方案不存在");
        }

        if (scheme.getRightt() != 0){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"该方案已经确认无法删除");
        }

        //删除
        removeById(id);

        //删除预购
        ExecutionDelete executionDelete = new ExecutionDelete();
        executionDelete.setSchemeid(scheme.getId());
        executionService.down(executionDelete);

        return 1;
    }

    /**
     * 方案确认
     *
     * @param id
     */
    @Override
    public Integer ok(Integer id) {

        //判断当前方案是否存在
        scheme scheme = getById(id);

        if (scheme == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"方案不存在");
        }

        if (scheme.getRightt() != 0){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"该方案已经确认了");
        }

        //修改当前方案状态
        scheme.setRightt(1);

        //修改
        updateById(scheme);

        //删除预购
        ExecutionDelete executionDelete = new ExecutionDelete();
        executionDelete.setSchemeid(scheme.getId());
        executionService.down(executionDelete);

        return null;
    }

    /**
     * 商家或客户根据id获取方案
     *
     * @param schemeSelectById
     */
    @Override
    public scheme getid(SchemeSelectById schemeSelectById) {

        Integer merchantid = schemeSelectById.getMerchantid();

        Integer ownerid = schemeSelectById.getOwnerid();

        scheme scheme = getById(schemeSelectById.getSchemeid());

        if (scheme == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"传入的方案id不存在");
        }

        if (merchantid != null && Objects.equals(scheme.getMerchantid(), merchantid)){
            return scheme;
        }

        if (ownerid != null && Objects.equals(scheme.getOwnerid(), ownerid)){
            //不让客户查看总材料费用
            scheme.setMaterialsmoney(0);
            return scheme;
        }

        return null;
    }


    //添加方案参数校验
    private scheme pan(SchemeAdd schemeAdd) {

        if (schemeAdd.getOwnerid() == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未传入委托人");
        }

        if (schemeAdd.getMerchantid() == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未传入设计人");
        }

        if (schemeAdd.getDetailid() == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"没有传入明细表id");
        }

        if (schemeAdd.getOverr() == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"没有传入改方案预计审计结束时间");
        }


        //获取预购
        detail detail = detailService.getById(schemeAdd.getDetailid());

        //判断明细表是否存在
        if (detail == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "传入的明细表不存在");
        }

        //判断明细表是否完成
        if (detail.getBring() == 0){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"改明细表未完成");
        }

        //判断明细表和委托方是否对上
        if (!Objects.equals(detail.getUserid(), schemeAdd.getOwnerid())){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"该方案不属于当前委托方");
        }

        //根据标记获取明细的所有商品
        DetailDto detailDto = detailService.select(detail.getSign());

        //获取所有商品
        List<signSelect> list = detailDto.getList();

        //根据商品id查询商品的总进价
        ResponseResult<Integer> result = shoppingFeign.MaterialsMoney(list);

        if (result.getData() == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, result.getMsg());
        }

        scheme scheme = new scheme();

        //属性拷贝
        BeanUtils.copyProperties(schemeAdd,scheme);

        //设置方案创建的审计时间
        scheme.setTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd: HH:mm:ss")));

        //设置总材料费用
        scheme.setMaterialsmoney(result.getData());

        //设置总金额
        scheme.setMoney(detail.getMoney());

        return scheme;

    }


    //判断商家
    private void panMerchant(Integer id) {
        if (id == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "为传入方案设计人");
        } else {
            merchantDto merchantDto = merchantFeign.select(new UserSelect(id, null)).getData();

            if (merchantDto == null) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "添加的设计人不存在");
            }

            if (merchantDto.getPermission() == 0) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "添加的设计人权限不够");
            }

        }
    }

}
